#!/usr/bin/python3
# -*- coding: utf-8; tab-width: 4; indent-tabs-mode: t -*-

import os
import dbus
import json
import argparse


def parseArgs():
    argParser = argparse.ArgumentParser()
    subParsers = argParser.add_subparsers()

    apShow = subParsers.add_parser("show")
    apShow.set_defaults(subcmd="show")

    apServerGenClientCert = subParsers.add_parser("generate-client-script")
    apServerGenClientCert.set_defaults(subcmd="generate-client-script")
    apServerGenClientCert.add_argument("vpns_type", metavar="vpn-server-type")
    apServerGenClientCert.add_argument("os_type", metavar="os-type")

    return argParser.parse_args()


def cmdShow():
    dbusObj = dbus.SystemBus().get_object('org.fpemud.WRT', '/org/fpemud/WRT')
    if dbusObj is None:
        raise Exception("not started")
    info = json.loads(dbusObj.GetRouterInfo(dbus_interface="org.fpemud.WRT"))

    print("Router Information:")
    if True:
        if "hostname" in info:
            print("    Hostname: " + info["hostname"])
        else:
            print("    Hostname: None")
        print("    UUID:     " + info["uuid"])
    print("")

    print("Internet Connection:")
    if "wconn-plugin" not in info:
        print("    None.")
    else:
        print("    Plugin: " + info["wconn-plugin"]["name"])
        if info["wconn-plugin"]["is-connected"]:
            print("    Status: Connected")
            if info["wconn-plugin"]["is-ip-public"] is None:
                print("    IP:     " + info["wconn-plugin"]["ip"])
            elif info["wconn-plugin"]["is-ip-public"]:
                print("    IP:     " + info["wconn-plugin"]["ip"] + " (public)")
            else:
                print("    IP:     " + info["wconn-plugin"]["ip"] + " (behind NAT)")
        else:
            print("    Status: Not connected")
    print("")

    if len(info["wan-service"]) > 0:
        print("WAN Services:")
        for item in info["wan-service"]:
            print("    " + item)
        print("")

    # if len(info["lan-service"]) > 0:
    #     print("LAN Services:")
    #     for item in info["lan-service"]:
    #         print("    localhost: " + item)
    #     print("")

    if len(info["tfac-group"]) > 0:
        print("Traffic Facility Groups:")
        for name in info["tfac-group"].keys():
            print("    %s" % (name))
        print("")

    while "cascade" in info:
        myData = info["cascade"]["router-list"][info["cascade"]["my-id"]]
        if "parent" not in myData:
            break
        print("Cascade Upstream:")
        print("    Plugin: " + info["wvpn-plugin"]["name"])
        if True:
            upstreamId = myData["parent"]
            upstreamData = info["cascade"]["router-list"][upstreamId]
            if "hostname" in upstreamData:
                upstreamName = "%s(%s)" % (upstreamData["hostname"], upstreamId)
            else:
                upstreamName = upstreamId
            print("    Name:   " + upstreamName)
        print("")
        break

    while "cascade" in info:
        downstreamIdList = []
        for routerId, routerData in info["cascade"]["router-list"].items():
            if routerData.get("parent", None) == info["cascade"]["my-id"]:
                downstreamIdList.append(routerId)
        if len(downstreamIdList) == 0:
            break
        print("Cascade Downstream:")
        for downstreamId in downstreamIdList:
            downstreamData = info["cascade"]["router-list"][downstreamId]
            if "hostname" in downstreamData:
                downstreamName = "%s(%s)" % (downstreamData["hostname"], downstreamId)
            else:
                downstreamName = downstreamId
            print("    " + downstreamName)
        print("")
        break

    print("Clients:")
    if "cascade" in info:
        for routerId, routerData in info["cascade"]["router-list"].items():
            if "client-list" in routerData:
                if "hostname" in routerData:
                    routerName = "%s(%s)" % (routerData["hostname"], routerId)
                else:
                    routerName = routerId
                print("    " + routerName + ":")
                if len(routerData["client-list"]) == 0:
                    print("        No client.")
                else:
                    for clientIp, clientData in routerData["client-list"].items():
                        if "hostname" in clientData:
                            clientName = "%s(%s)" % (clientData["hostname"], clientIp)
                        else:
                            clientName = clientIp
                        print("        " + clientName)
    else:
        print("Not implemented yet.")
    print("")


def cmdGenerateClientScript(vpns_plugin_full_name, ostype):
    dbusObj = dbus.SystemBus().get_object('org.fpemud.WRT', '/org/fpemud/WRT')
    if dbusObj is None:
        raise Exception("not started")

    fn, buf, warnList = dbusObj.GenerateClientScript(vpns_plugin_full_name, ostype, dbus_interface="org.fpemud.WRT")
    with open(fn, "w") as f:
        f.write(buf)
    os.chmod(fn, 0o755)

    print("Client script generated as \"./%s\"." % (fn))
    for warn in warnList:
        print("WARN: %s" % (warn))


if __name__ == "__main__":
    parseResult = parseArgs()
    if parseResult.subcmd == "show":
        cmdShow()
    elif parseResult.subcmd == "generate-client-script":
        cmdGenerateClientScript(parseResult.vpns_type, parseResult.os_type)
    else:
        raise Exception("Invalid command")


# class _AsciiTree:

#     def __init__(self, name):
#         assert len(name) > 0
#         self.name = name
#         self.children = []

#     def add_child(self, name):
#         assert len(name) > 0
#         return self.children.append(_AsciiTree(name))

#     def get_ascii(self):
#         nameLenList = []
#         i = 0
#         while True:
#             ret = self._get_namelen(i)
#             if ret == 0:
#                 break
#             nameLenList.append(ret)
#             i += 1
#         return ""           # fixme

#     def _get_namelen(self, level):
#         if level == 0:
#             return len(self.name)
#         else:
#             ret = 0
#             for child in self.children:
#                 ret = max(ret, child._get_namelen(level - 1))
#             return ret

# def _showOneClient(self, ip, hostname):
#     if hostname != "":
#         hostnameStr = "%s (%s)" % (hostname, ip)
#     else:
#         hostnameStr = "(%s)" % (ip)
#     fname = os.path.join(self.param.tmpDir, "subhosts.d", "owner.%s" % (ip))
#     if not os.path.exists(fname):
#         print("    " + hostnameStr)
#     else:
#         print(hostnameStr + ":")
#         for sip, shostname in WrtUtil.readDnsmasqHostFile(fname):
#             print("        " + shostname + " (" + sip + ")")

# def _addIndent(self, msg):
#     assert not msg.endswith("\n")
#     linelist = msg.split("\n")
#     linelist = ["    " + x for x in linelist]
#     return "\n".join(linelist)
